/**
 * moieo.net
 * @author Moieo
 */
package cn.moieo.carcontrol.view

import androidx.compose.foundation.Canvas
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import kotlin.math.atan2
import kotlin.math.pow
import kotlin.math.sqrt

/** 可交互的虚拟摇杆组件 */
@Preview
@Composable
fun RockerView(
    modifier: Modifier = Modifier,
    size: Dp = 200.dp,
    areaColor: Color = Color.Gray.copy(alpha = 0.5f),
    rockerColor: Color = Color.Gray.copy(alpha = 0.4f),
    directionMode: DirectionMode = DirectionMode.DIRECTION_8,
    maxDistanceLevel: Int = 100,
    onDirectionChanged: (Direction) -> Unit = {},
    onAngleChanged: (Double) -> Unit = {},
    onDistanceLevelChanged: (Int) -> Unit = {}
) {
    // 密度转换相关计算
    val density = LocalDensity.current
    val areaRadiusPx = with(density) { size.toPx() / 2 }
    val rockerRadiusPx = areaRadiusPx * 0.3f // 摇杆半径

    // 状态管理
    var center by remember { mutableStateOf(Offset(areaRadiusPx, areaRadiusPx)) }
    var rockerPosition by remember { mutableStateOf(center) }

    Box(
        modifier = modifier
            .size(size)
            .pointerInput(Unit) {
                detectDragGestures(
                    onDragStart = { offset ->
                        // 初始化中心点位置
                        center = Offset(areaRadiusPx, areaRadiusPx)
                        rockerPosition = center
                    },
                    onDrag = { change, _ ->
                        // 处理拖动逻辑
                        val newPosition = calculateRockerPosition(
                            center,
                            change.position,
                            areaRadiusPx,
                            rockerRadiusPx
                        )
                        rockerPosition = newPosition
                        handleCallbacks(
                            center,
                            rockerPosition,
                            directionMode,
                            areaRadiusPx,
                            rockerRadiusPx,
                            maxDistanceLevel,
                            onDirectionChanged,
                            onAngleChanged,
                            onDistanceLevelChanged
                        )
                    },
                    onDragEnd = {
                        // 复位处理
                        rockerPosition = center
                        onDirectionChanged(Direction.CENTER)
                        onAngleChanged(0.0)
                    }
                )
            }
    ) {
        // 绘制背景圆形区域
        Canvas(modifier = Modifier.fillMaxSize()) {
            drawCircle(color = areaColor, radius = areaRadiusPx, center = center)
        }

        // 绘制可拖动摇杆
        Canvas(
            modifier = Modifier
                .offset {
                    IntOffset(
                        (rockerPosition.x - rockerRadiusPx).toInt(),
                        (rockerPosition.y - rockerRadiusPx).toInt()
                    )
                }
                .size((rockerRadiusPx * 2).dp)
        ) {
            drawCircle(
                color = rockerColor,
                radius = rockerRadiusPx,
                center = Offset(rockerRadiusPx, rockerRadiusPx)
            )
        }
    }
}


/** 计算摇杆的实际位置（带边界限制） */
private fun calculateRockerPosition(
    center: Offset,
    touchPoint: Offset,
    areaRadius: Float,
    rockerRadius: Float
): Offset {
    val vector = touchPoint - center
    val distance = sqrt(vector.x.pow(2) + vector.y.pow(2))
    val maxDistance = areaRadius - rockerRadius

    return if (distance <= maxDistance) {
        touchPoint
    } else {
        val ratio = maxDistance / distance
        center + vector * ratio
    }
}

/** 处理所有回调触发逻辑 */
private fun handleCallbacks(
    center: Offset,
    current: Offset,
    directionMode: DirectionMode,
    areaRadius: Float,
    rockerRadiusPx: Float, // 添加 rockerRadiusPx 参数
    maxDistanceLevel: Int,
    onDirectionChanged: (Direction) -> Unit,
    onAngleChanged: (Double) -> Unit,
    onDistanceLevelChanged: (Int) -> Unit
) {
    // 计算并标准化角度
    val angle = Math.toDegrees(atan2(current.y - center.y, current.x - center.x).toDouble())
    val normalizedAngle = (angle + 360) % 360
    onAngleChanged(normalizedAngle)

    // 计算距离等级，并设置最大值为 maxDistanceLevel
    val distance = sqrt((current.x - center.x).pow(2) + (current.y - center.y).pow(2))
    val maxReachableDistance = areaRadius - rockerRadiusPx // 摇杆可以到达的最大距离
    val level =
        ((distance / maxReachableDistance) * maxDistanceLevel).toInt().coerceIn(0, maxDistanceLevel)
    onDistanceLevelChanged(level)

    // 根据模式获取方向
    val direction = when (directionMode) {
        DirectionMode.DIRECTION_2_HORIZONTAL -> getHorizontalDirection(normalizedAngle)
        DirectionMode.DIRECTION_2_VERTICAL -> getVerticalDirection(normalizedAngle)
        DirectionMode.DIRECTION_4_ROTATE_0 -> getFourDirection(normalizedAngle)
        DirectionMode.DIRECTION_4_ROTATE_45 -> getFourDirectionRotated(normalizedAngle)
        DirectionMode.DIRECTION_8 -> getEightDirection(normalizedAngle)
    }
    onDirectionChanged(direction)
}

/** 水平双方向判断 */
private fun getHorizontalDirection(angle: Double): Direction {
    return if (angle in 90.0..270.0) Direction.LEFT else Direction.RIGHT
}

/** 垂直双方向判断 */
private fun getVerticalDirection(angle: Double): Direction {
    return if (angle in 0.0..180.0) Direction.DOWN else Direction.UP
}

/** 四方向判断（标准模式） */
private fun getFourDirection(angle: Double): Direction {
    return when (angle) {
        in 45.0..135.0 -> Direction.DOWN
        in 135.0..225.0 -> Direction.LEFT
        in 225.0..315.0 -> Direction.UP
        else -> Direction.RIGHT
    }
}

/** 四方向判断（45度旋转模式） */
private fun getFourDirectionRotated(angle: Double): Direction {
    return when (angle) {
        in 22.5..112.5 -> Direction.DOWN_LEFT
        in 112.5..202.5 -> Direction.LEFT
        in 202.5..292.5 -> Direction.UP_LEFT
        else -> Direction.RIGHT
    }
}

/** 八方向精确判断 */
private fun getEightDirection(angle: Double): Direction {
    return when {
        angle < 22.5 || angle >= 337.5 -> Direction.RIGHT
        angle < 67.5 -> Direction.DOWN_RIGHT
        angle < 112.5 -> Direction.DOWN
        angle < 157.5 -> Direction.DOWN_LEFT
        angle < 202.5 -> Direction.LEFT
        angle < 247.5 -> Direction.UP_LEFT
        angle < 292.5 -> Direction.UP
        else -> Direction.UP_RIGHT
    }
}

/** 方向枚举定义 */
enum class Direction {
    LEFT, RIGHT, UP, DOWN,
    UP_LEFT, UP_RIGHT,
    DOWN_LEFT, DOWN_RIGHT,
    CENTER
}

/** 方向模式枚举 */
enum class DirectionMode {
    DIRECTION_2_HORIZONTAL,   // 水平双方向
    DIRECTION_2_VERTICAL,     // 垂直双方向
    DIRECTION_4_ROTATE_0,    // 四方向标准
    DIRECTION_4_ROTATE_45,    // 四方向旋转45度
    DIRECTION_8               // 八方向
}